﻿using System;
using System.Threading;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace fastCSharp.threading
{
    /// <summary>
    /// 线程池线程
    /// </summary>
    internal sealed class thread
    {
        /// <summary>
        /// 线程池线程集合
        /// </summary>
        private static readonly indexPool<Thread> threads = new indexPool<Thread>();
        /// <summary>
        /// 线程池线程默认堆栈帧数
        /// </summary>
        internal static int DefaultFrameCount;
        /// <summary>
        /// 活动的线程池线程集合
        /// </summary>
        public static subArray<Thread> Threads
        {
            get
            {
                return threads.GetArray();
            }
        }
        /// <summary>
        /// 线程池
        /// </summary>
        private readonly threadPool threadPool;
        /// <summary>
        /// 线程句柄
        /// </summary>
        private readonly Thread threadHandle;
        /// <summary>
        /// 等待事件
        /// </summary>
        private readonly EventWaitHandle waitHandle;
        /// <summary>
        /// 线程ID
        /// </summary>
        public int ManagedThreadId
        {
            get { return threadHandle.ManagedThreadId; }
        }
        /// <summary>
        /// 任务委托
        /// </summary>
        private Action task;
        /// <summary>
        /// 应用程序退出处理
        /// </summary>
        private Action domainUnload;
        /// <summary>
        /// 应用程序退出处理
        /// </summary>
        private Action<Exception> onError;
        /// <summary>
        /// 线程索引位置
        /// </summary>
        private int threadIndex;
        /// <summary>
        /// 线程池线程
        /// </summary>
        /// <param name="threadPool">线程池</param>
        /// <param name="stackSize">堆栈大小</param>
        /// <param name="task">任务委托</param>
        /// <param name="domainUnload">应用程序退出处理</param>
        /// <param name="onError">应用程序退出处理</param>
        internal thread(threadPool threadPool, int stackSize, Action task, Action domainUnload, Action<Exception> onError)
        {
            this.task = task;
            this.domainUnload = domainUnload;
            this.onError = onError;
            waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, null);
            this.threadPool = threadPool;
            threadHandle = new Thread(run, stackSize);
            threadHandle.IsBackground = true;
            threadIndex = threads.Push(threadHandle);
            threadHandle.Start();
        }
        /// <summary>
        /// 运行线程
        /// </summary>
        private void run()
        {
#pragma warning disable 618
            if (DefaultFrameCount == 0) DefaultFrameCount = new System.Diagnostics.StackTrace(threadHandle, false).FrameCount;
#pragma warning restore 618
            do
            {
                if (domainUnload != null) fastCSharp.domainUnload.Add(domainUnload);
                try
                {
                    task();
                }
                catch (Exception error)
                {
                    if (onError != null)
                    {
                        try
                        {
                            onError(error);
                        }
                        catch (Exception error1)
                        {
                            log.Error.Add(error1, null, false);
                        }
                    }
                    else log.Error.Add(error, null, false);
                }
                finally
                {
                    task = null;
                    onError = null;
                    if (domainUnload != null)
                    {
                        fastCSharp.domainUnload.Remove(domainUnload, false);
                        domainUnload = null;
                    }
                }
                threadPool.Push(this);
                waitHandle.WaitOne();
            }
            while (task != null);
            threads.UnsafeFree(threadIndex);
            waitHandle.Close();
        }
        /// <summary>
        /// 结束线程
        /// </summary>
        [MethodImpl((MethodImplOptions)fastCSharp.pub.MethodImplOptionsAggressiveInlining)]
        internal void Stop()
        {
            waitHandle.Set();
        }
        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="task">任务委托</param>
        /// <param name="domainUnload">应用程序退出处理</param>
        /// <param name="onError">应用程序退出处理</param>
        [MethodImpl((MethodImplOptions)fastCSharp.pub.MethodImplOptionsAggressiveInlining)]
        internal void RunTask(Action task, Action domainUnload, Action<Exception> onError)
        {
            this.domainUnload = domainUnload;
            this.onError = onError;
            this.task = task;
            waitHandle.Set();
        }
    }
}
